{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "revolutionary-headquarters",
   "metadata": {},
   "source": [
    "# Calculate Image Moments of an Ellipse\n",
    "\n",
    "Image moments can be used to determine the center of gravity or average pixel location of a binary object as well as the orientation of an object according to its axes of variation.\n",
    "\n",
    "The interactive plot below demonstrates how to calculate the image moments of an ellipse-defined mask."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "amino-atlantic",
   "metadata": {},
   "outputs": [],
   "source": [
    "import itk\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "from ipywidgets import interact\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "domestic-jenny",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "9460aeb87fea499c90c4e301da10ddce",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(IntSlider(value=30, description='tx'), IntSlider(value=50, description='ty'), IntSlider(…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "output_size = [100, 100]  # size of binary image containing the ellipse\n",
    "\n",
    "\n",
    "@interact(\n",
    "    tx=(0, output_size[0], 1),\n",
    "    ty=(0, output_size[1], 1),\n",
    "    a=(5, 50, 1),\n",
    "    b=(5, 50, 1),\n",
    "    theta=(0, 2 * np.pi, 0.1),\n",
    ")\n",
    "def foo(tx=30, ty=50, a=5, b=10, theta=np.pi / 4.0):\n",
    "    \"\"\"\n",
    "    Creates a binary image of an ellipse and calculates the image moments.  Major (purple) and minor (green)\n",
    "    principal axes are displayed.\n",
    "\n",
    "    Parameters\n",
    "    ==========\n",
    "    tx, ty : translation x and y\n",
    "    a, b : ellipse horizontal and vertical widths before rotation\n",
    "    theta : angle of rotation (radians)\n",
    "    \"\"\"\n",
    "\n",
    "    # ellipse starts as unit circle, use world transform to define final ellipse\n",
    "    ellipse = itk.EllipseSpatialObject[2].New()\n",
    "    ellipse_transform = itk.AffineTransform[itk.D, 2].New()\n",
    "    ellipse_transform.Scale([a, b])\n",
    "    ellipse_transform.Rotate2D(theta)\n",
    "    ellipse_transform.Translate([tx, ty])\n",
    "    ellipse.SetObjectToWorldTransform(ellipse_transform)\n",
    "\n",
    "    ellipse_img = itk.spatial_object_to_image_filter(\n",
    "        input=ellipse, inside_value=1, outside_value=0, size=output_size\n",
    "    )\n",
    "\n",
    "    momentor = itk.ImageMomentsCalculator.New(Image=ellipse_img)\n",
    "    momentor.Compute()\n",
    "\n",
    "    centroid = momentor.GetCenterOfGravity()\n",
    "    prin_axes = itk.array_from_matrix(momentor.GetPrincipalAxes())\n",
    "    minor_axes = prin_axes[0]\n",
    "    major_axes = prin_axes[1]\n",
    "\n",
    "    fig, ax = plt.subplots(figsize=[8, 8])\n",
    "    plt.imshow(ellipse_img, cmap=\"gray\")\n",
    "    plt.scatter(centroid[0], centroid[1])\n",
    "\n",
    "    minor_pt = centroid + minor_axes * 5\n",
    "    plt.plot([centroid[0], minor_pt[0]], [centroid[1], minor_pt[1]], color=\"green\")\n",
    "\n",
    "    major_pt = centroid + major_axes * 5\n",
    "    plt.plot([centroid[0], major_pt[0]], [centroid[1], major_pt[1]], color=\"purple\")\n",
    "\n",
    "    print(momentor)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "seasonal-sandwich",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
